package com.tinusgraglin.enclusiv.datalayer.datasources

import com.squareup.moshi.JsonDataException
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okio.IOException
import org.json.JSONObject
import com.tinusgraglin.enclusiv.datalayer.Exceptions.*
import com.tinusgraglin.enclusiv.datalayer.RemoteSourceCommunication

class UserRegistrationRemoteSource (private val communication: RemoteSourceCommunication) {
    private val serverUrl = communication.serverUrl
    private val client = communication.client

    fun sendVerificationCodeToEmail(email: String) {
        val requestUrl = serverUrl.newBuilder()
            .addPathSegments("checkcode/get")
            .addQueryParameter("email", email)
            .build()

        val request = Request.Builder()
            .url(requestUrl)
            .build()

        val resp = client.newCall(request).execute()

        if(!resp.isSuccessful)
            throw IOException("Request Error: ${resp.code}")
    }

    fun checkVerificationCode(email: String, code: String): Boolean {
        val requestUrl = serverUrl.newBuilder()
            .addPathSegments("checkcode/check")
            .addQueryParameter("email", email)
            .addQueryParameter("code", code)
            .build()

        val request = Request.Builder()
            .url(requestUrl)
            .build()

        val resp = client.newCall(request).execute()

        if (!resp.isSuccessful) {
            throw IOException("Request Error: ${resp.code}")
        } else {
            val responseStr = resp.body.string()

            val pairResponse = communication.resultStrBoolDataResponseAdapter.fromJson(responseStr)
                ?: throw JsonDataException("Data conversion failed.")

            when (pairResponse.result.lowercase()) {
                "code not the same" -> throw VerificationCodeNotMatch()
                "code not exist" -> throw VerificationEntryNotExist()
                "success" -> return true
                else -> throw IllegalStateException("Unexpected Result String")
            }
        }
    }

    fun register(email: String, password: String): Long {
        val requestUrl = serverUrl.newBuilder()
            .addPathSegments("account/register")
            .build()

        val requestBody = JSONObject().apply {
            put("email", email)
            put("password", password)
        }.toString()

        val request = Request.Builder()
            .url(requestUrl)
            .post(requestBody.toRequestBody("application/json".toMediaType()))
            .build()

        val resp = client.newCall(request).execute()

        if (!resp.isSuccessful) {
            throw IOException("Request Error: ${resp.code}")
        } else {
            val responseStr = resp.body.string()

            val pairResponse = communication.resultStrLongDataResponseAdapter.fromJson(responseStr)
                ?: throw JsonDataException("Data conversion failed.")

            when (pairResponse.result) {
                "email already registered" -> throw EmailRegistered()
                "success" -> return pairResponse.data!!
                else -> throw IllegalStateException("Unexpected Result String")
            }
        }
    }
}